﻿#include "Audio_Resampler.h"
#include <QDebug>
extern "C" {
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libswresample/swresample.h"
#include "libavutil/samplefmt.h"
#include "libavutil/frame.h"
}
Audio_Resampler::Audio_Resampler()
{
}

bool Audio_Resampler::Open(int in_samplerate, int in_channels, AVSampleFormat in_format,
                          int out_samplerate, int out_channels, AVSampleFormat out_format)
{
    if (swr_Context_ == nullptr) {
        swr_Context_ = swr_alloc();
        int64_t in_channels_layout = av_get_default_channel_layout(in_channels);
        av_opt_set_int(swr_Context_, "in_channel_layout", in_channels_layout, 0);
        av_opt_set_int(swr_Context_, "in_sample_rate", in_samplerate, 0);
        av_opt_set_sample_fmt(swr_Context_, "in_sample_fmt", in_format, 0);

        av_opt_set_int(swr_Context_, "out_channel_layout",AV_CH_LAYOUT_STEREO, 0);
        av_opt_set_int(swr_Context_, "out_sample_rate", out_samplerate, 0);
        av_opt_set_sample_fmt(swr_Context_, "out_sample_fmt", out_format, 0);

        int ret = swr_init(swr_Context_);
        if (ret < 0) {
            char errorBuf[AV_ERROR_MAX_STRING_SIZE];
            av_strerror(ret, errorBuf, AV_ERROR_MAX_STRING_SIZE);
            qDebug() << "Failed to initialize audio resampler: " << ret << errorBuf;
            return false;
        }

        in_samplerate_ = in_samplerate;
        in_channels_ = in_channels;
        in_format_ = in_format;
        out_samplerate_ = out_samplerate;
        out_channels_ = out_channels;
        out_format_ = out_format;
        return true;
    }

    return false;
}

int Audio_Resampler::Convert(AVFramePtr in_frame, AVFramePtr& out_frame)
{
    if (swr_Context_ == nullptr) {
        return -1;
    }
    out_frame = AVFramePtr(av_frame_alloc(), [](AVFrame* p) {av_frame_free(&p);});
    out_frame->sample_rate = out_samplerate_;
    out_frame->format = out_format_;
    out_frame->channels = out_channels_;
    out_frame->channel_layout = AV_CH_LAYOUT_STEREO;

    // 从采样器中会缓存一部分，获取缓存的长度
    int64_t delay = swr_get_delay(swr_Context_, in_frame->sample_rate);
    out_frame->nb_samples = av_rescale_rnd(delay + in_frame->nb_samples, out_samplerate_, in_frame->sample_rate, AV_ROUND_UP);
    out_frame->pts = out_frame->pkt_dts = in_frame->pts;

    if (av_frame_get_buffer(out_frame.get(), 0) != 0) {
        return -1;
    }

    int len = swr_convert(swr_Context_, (uint8_t**)&out_frame->data, out_frame->nb_samples, (const uint8_t**)in_frame->data, in_frame->nb_samples);
    if (len < 0) {
        out_frame.reset();
        out_frame = nullptr;
        qDebug() << "swr_convert() failed.";
        return - 1;
    }
    out_frame->nb_samples = len;
    return len;
}

void Audio_Resampler::Close()
{
    if (swr_Context_ != nullptr) {
        if (swr_is_initialized(swr_Context_)) {
            swr_close(swr_Context_);
        }
        swr_free(&swr_Context_);
        swr_Context_ = nullptr;
    }
}

Audio_Resampler::~Audio_Resampler()
{
    Close();
}
